package com.yonyou.ucf.mdf.app.isvdxq.yonyisv.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.yonyou.ucf.mdf.app.isvdxq.common.DxqConfig;
import com.yonyou.ucf.mdf.app.isvdxq.yonyisv.model.EventContent;
import com.yonyou.ucf.mdf.app.isvdxq.common.ISVEventType;
import com.yonyou.ucf.mdf.app.isvdxq.common.SuiteConfig;
import com.yonyou.ucf.mdf.app.isvdxq.crypto.EncryptionHolder;
import com.yonyou.ucf.mdf.app.isvdxq.crypto.IsvEventCrypto;
import com.yonyou.ucf.mdf.app.isvdxq.other.service.*;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Arrays;

/**
 * 处理租户数据变更的回调事件。
 * 该回调地址填写在套件的 “订阅” 弹出框中。
 */
@RequestMapping(value = {DxqConfig.pre_apiUrl+"/pushevent",DxqConfig.pre_pcUrl+"/pushevent"})
@RestController
public class PushEventReceiveController {


    private static Logger LOGGER = LoggerFactory.getLogger(PushEventReceiveController.class);

    @Autowired
    private SuiteConfig suiteConfig;
    @Autowired
    private BaseService baseService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ManageClassService manageClassService;
    @Autowired
    private ProductSKUService productSKUService;
    @Autowired
    private UnitService unitService;
    @Autowired
    private UnitassistService unitassistService;
    @Autowired
    private ProductSKUTempService productSKUTempService;

    @Autowired
    private ProductSpecService productSpecService;

    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private TranstypeService transtypeService;
    @Autowired
    private OrgUnitService orgUnitService;

    private ObjectMapper mapper = new ObjectMapper();

    @Value("${ucf.mdd.open-api.isv-app-key}")
    private String appKey;

    @Value("${ucf.mdd.open-api.isv-app-secret}")
    private String appSecrect;

    @SneakyThrows
    @PostMapping("/open/event_push")
    public String eventCallBackReceiver(@RequestBody EncryptionHolder holder) {

        // 构建解密验签处理对象
        IsvEventCrypto crypto = new IsvEventCrypto(appSecrect, suiteConfig.getEncodingAESKey(), appKey);
        // 验签解密后的消息体
        String decryptMessage = crypto.decryptMsg(holder);
        // 反序列化后的消息内容对象
        EventContent content = mapper.readValue(decryptMessage, EventContent.class);

        System.out.println("/open/event_push");
        String logtxt = String.format("新的事件推送[{}]，content: {}", content.getType(), new Gson().toJson(holder));
        System.out.println(logtxt);
        logtxt = String.format("新的事件推送[{}]，content: {}", content.getType(), content.getContent());
        System.out.println(logtxt);

        eventWorking(content);

        // 处理成功，回复 "success" 告知开放平台，否则开放平台会重试推送，直到 24 小时
        return "success";
    }

    /**
     * 新版生态应用接受消息不需要传递  EncodingAESKey 参数  系统自动计算
     *
     * @param holder
     * @return
     * @throws IOException
     */
    @SneakyThrows
    @PostMapping("/open/event_push_v2")
    public String eventCallBackReceiverV2(@RequestBody EncryptionHolder holder) {
        // 构建解密验签处理对象
        IsvEventCrypto crypto = new IsvEventCrypto(appSecrect, null, appKey);
        // 验签解密后的消息体
        String decryptMessage = crypto.decryptMsg(holder);
        // 反序列化后的消息内容对象
        EventContent content = mapper.readValue(decryptMessage, EventContent.class);

        System.out.println("/open/event_push_v2");
        String logtxt = String.format("新的事件推送[{}]，content: {}", content.getType(), new Gson().toJson(holder));
        System.out.println(logtxt);
        logtxt = String.format("新的事件推送[{}]，content: {}", content.getType(), content.getContent());
        System.out.println(logtxt);

        eventWorking(content);

        // 处理成功，回复 "success" 告知开放平台，否则开放平台会重试推送，直到 24 小时
        return "success";
    }

    private void eventWorking(EventContent content) throws IOException {
        String myType = content.getType();
        System.out.println(String.format("[eventWorking]tid:%s,authtid:%s,userId:%s", content.getTenantId(), content.getAuthTenantId(), Arrays.toString(content.getUserId())));
        // 根据事件类型进行相关处理操作，耗时操作推荐异步处理，平台默认推送超时时间为 5 秒，超时视为推送失败
        switch (myType) {
            //业务单元 BASE_ORG_EVENT_ADD_AFTER、BASE_ORG_EVENT_UPDATE_AFTER、BASE_ORG_EVENT_DELETE_AFTER BASE_ORG_EVENT_DISABLE_AFTER、BASE_ORG_EVENT_ENABLE_AFTER
            case "BASE_ORG_EVENT_DELETE_AFTER":
                LOGGER.info("事件类型: {}, 说明: 业务单元删除", content.getType());
                int flagOrgUnitDel = orgUnitService.EventDel(content);
                if (flagOrgUnitDel > 0) {
                    LOGGER.info("业务单元删除订阅成功{}", flagOrgUnitDel);
                }
                break;
            case "BASE_ORG_EVENT_ADD_AFTER":
            case "BASE_ORG_EVENT_UPDATE_AFTER":
                LOGGER.info("事件类型: {}, 说明: 业务单元编辑", content.getType());
                orgUnitService.AutoDataEdit(content);
                LOGGER.info("业务单元编辑订阅成功{}");
                break;
            //交易类型
            case "transtype_stop":
            case "transtype_unstop":
                LOGGER.info("事件类型: {}, 说明: 交易类型停用启用", content.getType());
                break;
            case "transtype_delete":
                LOGGER.info("事件类型: {}, 说明: 交易类型删除", content.getType());
                int flagTranstypeDel = transtypeService.EventDel(content);
                if (flagTranstypeDel > 0) {
                    LOGGER.info("交易类型订阅成功{}", flagTranstypeDel);
                }
                break;
            case "transtype_add":
            case "transtype_update":
                LOGGER.info("事件类型: {}, 说明: 交易类型编辑", content.getType());
                int flagTranstypeEdit = transtypeService.EventEdit(content);
                if (flagTranstypeEdit > 0) {
                    LOGGER.info("交易类型订阅成功{}", flagTranstypeEdit);
                }
                break;
            //仓库
            case "YXYBASEDOC_AA_WAREHOUSE_DELETE":
                LOGGER.info("事件类型: {}, 说明: 仓库删除", content.getType());
                int flagWarehouseDel = warehouseService.EventDel(content);
                if (flagWarehouseDel > 0) {
                    LOGGER.info("仓库订阅成功{}", flagWarehouseDel);
                }
                break;
            case "YXYBASEDOC_AA_WAREHOUSE_INSERT":
            case "YXYBASEDOC_AA_WAREHOUSE_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 仓库编辑", content.getType());
                try {
                    warehouseService.AutoDataEdit(content);
                } catch (Exception ex) {
                    LOGGER.info("[仓库编辑]{}", ex.getMessage());
                }
                break;
            //计量单位
            case "YXYBASEDOC_PC_UNIT_DELETE":
                LOGGER.info("事件类型: {}, 说明: 计量单位删除", content.getType());
                int flagUnitDel = unitService.EventDel(content);
                if (flagUnitDel > 0) {
                    LOGGER.info("计量单位订阅成功{}", flagUnitDel);
                }
                break;
            case "YXYBASEDOC_PC_UNIT_INSERT":
            case "YXYBASEDOC_PC_UNIT_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 计量单位编辑", content.getType());
                int flagUnitEdit = unitService.EventEdit(content);
                if (flagUnitEdit > 0) {
                    LOGGER.info("计量单位订阅成功{}", flagUnitEdit);
                }
                break;
            //物料SKU
            case "YXYBASEDOC_PC_PRODUCTSKUPRO_DELETE":
                LOGGER.info("事件类型: {}, 说明: 物料SKU删除", content.getType());
                int flagProductSKUDel = productSKUService.EventDel(content);
                if (flagProductSKUDel > 0) {
                    LOGGER.info("物料档案SKU订阅成功{}", flagProductSKUDel);
                }
                break;
            case "YXYBASEDOC_PC_PRODUCTSKUPRO_INSERT":
            case "YXYBASEDOC_PC_PRODUCTSKUPRO_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 物料SKU编辑", content.getType());
                int flagProductSKUEdit = productSKUService.EventEdit(content);
                if (flagProductSKUEdit > 0) {
                    LOGGER.info("物料档案SKU订阅成功{}", flagProductSKUEdit);
                }
                break;
            //物料
            case "YXYBASEDOC_PC_PRODUCT_DELETE":
                LOGGER.info("事件类型: {}, 说明: 物料删除", content.getType());
                int flagProductDel = productService.EventDel(content);
                if (flagProductDel > 0) {
                    LOGGER.info("物料档案订阅成功{}", flagProductDel);
                }
                break;
            case "YXYBASEDOC_PC_PRODUCT_UPDATE":
            case "YXYBASEDOC_PC_PRODUCT_INSERT":
                LOGGER.info("事件类型: {}, 说明: 物料编辑", content.getType());
                try {
                    productService.AutoDataEdit(content);
                } catch (Exception ex) {
                    LOGGER.info("[物料编辑]{}", ex.getMessage());
                }
                break;
            case "YXYBASEDOC_PC_MANAGEMENTCLASS_INSERT":
            case "YXYBASEDOC_PC_MANAGEMENTCLASS_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 物料分类编辑", content.getType());
                int flagMANAGEMENTCLASSEdit = manageClassService.EventEdit(content);
                if (flagMANAGEMENTCLASSEdit > 0) {
                    LOGGER.info("物料分类订阅成功{}", flagMANAGEMENTCLASSEdit);
                }
                break;
            case "YXYBASEDOC_PC_MANAGEMENTCLASS_DELETE":
                LOGGER.info("事件类型: {}, 说明: 物料分类删除", content.getType());
                int flagMANAGEMENTCLASSDel = manageClassService.EventDel(content);
                if (flagMANAGEMENTCLASSDel > 0) {
                    LOGGER.info("物料分类订阅成功{}", flagMANAGEMENTCLASSDel);
                }
                break;
            case "YXYBASEDOC_PC_SPEPRO_INSERT":
            case "YXYBASEDOC_PC_SPEPRO_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 物料规格编辑", content.getType());
//                int flagSPEPROEdit = productSpecService.EventEdit(content);
//                if (flagSPEPROEdit > 0) {
//                    LOGGER.info("物料规格订阅成功{}", flagSPEPROEdit);
//                }
                break;
            case "YXYBASEDOC_PC_SPEPRO_DELETE":
                LOGGER.info("事件类型: {}, 说明: 物料规格删除", content.getType());
//                int flagSPEPRODel = productSpecService.EventDel(content);
//                if (flagSPEPRODel > 0) {
//                    LOGGER.info("物料规格订阅成功{}", flagSPEPRODel);
//                }
                break;

            case "CHECK_URL":
                LOGGER.info("事件类型: {}, 说明: 检查事件推送回调地址", ISVEventType.CHECK_URL);
                break;

            case "STAFF_ADD":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下员工增加, 员工变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getStaffId()));
                break;
            case "STAFF_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下员工更改, 员工变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getStaffId()));
                break;
            case "STAFF_ENABLE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下员工启用, 员工变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getStaffId()));
                break;
            case "STAFF_DISABLE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下员工停用, 员工变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getStaffId()));
                break;
            case "STAFF_DELETE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下员工删除, 员工变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getStaffId()));
                break;

            case "DEPT_ADD":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下部门创建, 部门变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getDeptId()));
                break;
            case "DEPT_UPDATE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下部门修改, 部门变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getDeptId()));
                break;
            case "DEPT_ENABLE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下部门修改, 部门变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getDeptId()));
                break;
            case "DEPT_DISABLE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下部门修改, 部门变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getDeptId()));
                break;
            case "DEPT_DELETE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下部门删除, 部门变更 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getDeptId()));
                break;
            case "USER_ADD":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下用户增加，用户 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getUserId()));
                break;
            case "USER_DELETE":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下用户移除，用户 id: {}", content.getType(), content.getTenantId(), Arrays.toString(content.getUserId()));
                break;
            case "APPROVAL_MEG":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 下用户移除", content.getType(), content.getTenantId());
                break;
            case "FRONT_LOGOUT":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 用户注销，信息: {}", content.getType(), content.getTenantId(), content.getContent());
                break;
            case "META_ALTER":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 元数据修改，信息: {}", content.getType(), content.getTenantId(), content.getContent());
                break;
            case "PROJECT_ADD":
                LOGGER.info("事件类型: {}, 说明: 租户 {} 元数据修改，信息: {}", content.getType(), content.getTenantId(), content.getContent());
                break;
            case "UNKNOWN":
            default:
                LOGGER.info("未知事件");
                break;
        }
    }
}
